from turtle import *
from math import *
import numpy as np


class PathButterfly:
    def __init__(self, a):
        self.a = a
        self.length = 2 * pi

    def get_path(self, t):
        x = self.a * sin(t) * (exp(cos(t)) - 2 * cos(4 * t) + pow(sin(t / 12), 5))
        y = self.a * cos(t) * (exp(cos(t)) - 2 * cos(4 * t) + pow(sin(t / 12), 5))

        dx = self.a * sin(t) * (8 * sin(4 * t) + (5 * cos(t / 12) * sin(t / 12) ** 4) / 12 - exp(cos(t)) * sin(t)) \
             + self.a * cos(t) * (exp(cos(t)) - 2 * cos(4 * t) + sin(t / 12) ** 5)
        dy = self.a * cos(t) * (8 * sin(4 * t) + (5 * cos(t / 12) * sin(t / 12) ** 4) / 12 - exp(cos(t)) * sin(t)) \
             - self.a * sin(t) * (exp(cos(t)) - 2 * cos(4 * t) + sin(t / 12) ** 5)

        ddx = self.a * exp(cos(t)) * sin(t) ** 3 - (149 * self.a * sin(t / 12) ** 5 * sin(t)) / 144 + 34 * self.a * cos(4 * t) * sin(t) \
              + 16 * self.a * sin(4 * t) * cos(t) - self.a * exp(cos(t)) * sin(t) + (
                          5 * self.a * cos(t / 12) * sin(t / 12) ** 4 * cos(t)) / 6 \
              - 3 * self.a * exp(cos(t)) * cos(t) * sin(t) + (5 * self.a * cos(t / 12) ** 2 * sin(t / 12) ** 3 * sin(t)) / 36
        ddy = self.a * cos(t) * (32 * cos(4 * t) - exp(cos(t)) * cos(t) + (5 * cos(t / 12) ** 2 * sin(t / 12) ** 3) / 36 - (
                    5 * sin(t / 12) ** 5) / 144 + exp(cos(t)) * sin(t) ** 2) \
              - self.a * cos(t) * (exp(cos(t)) - 2 * cos(4 * t) + sin(t / 12) ** 5) - 2 * self.a * sin(t) * (
                          8 * sin(4 * t) + (5 * cos(t / 12) * sin(t / 12) ** 4) / 12 - exp(cos(t)) * sin(t))

        return (x, y), (dx, dy), (ddx, ddy)

    def get_length(self):
        return self.length


if __name__ == '__main__':
    pensize(3)
    pencolor("blue")

    path_butterfly = PathButterfly(60)
    num = 1001

    t = np.linspace(0, np.pi * 24, num)
    for ti in t:
        goto(*(path_butterfly.get_path(ti)[0]))
